local heg_description = [==[
# 应变国战模式简介

本模式用于加入晋势力武将的应变国战模式。

《应变篇》是三国杀OL推出的全新牌扩，须替换国战标准版牌堆对应的卡牌进行游戏。

 基本游戏规则与国战标准模式相同。

**游戏开始时，会随机禁用一个势力，此势力的武将将不会在本局游戏中出现**

**本模式将池与全扩模式共享**

---

## 新机制：应变

在《应变篇》中，部分卡牌的牌面将带有特殊标记，标识此牌具有“应变”效果。具有这些标记的卡牌可符合对应的应变条件时触发其应变效果：

富甲：使用时手牌最多。

空巢：使用时没有手牌。

残躯：使用时体力值为1。

助战：指定目标后，除目标外的其他角色可以弃置一张同类别手牌，有角色响应后执行对应的效果。

疑兵：使用时有装备的角色中装备数为全场唯一最少。

---

 ## 新概念：冰属性伤害

冰属性是一种新的属性伤害，与火属性伤害和雷属性伤害一样，可以传导。

特别的，当你对一名角色造成冰属性伤害时，若其受到的不是传导伤害，你可以防止此伤害，依次弃置其两张牌。（类似于卡牌【寒冰剑】）

---

## 新概念：卜算

卜算是一种新的能力关键字，部分牌或技能将引入卜算的操作。

卜算X，即观看牌堆顶的X张牌，将其中任意张以任意顺序置于牌堆顶，其余以任意顺序置于牌堆底。（类似于诸葛亮的技能〖观星〗）。



]==]

local H = require "packages/ol_hegemony/util"


local heg

---@class HegLogic: GameLogic
local HegLogic = {}
function HegLogic:assignRoles()
  local room = self.room
  for _, p in ipairs(room.players) do
    room:setPlayerProperty(p, "role_shown", false) --1
    p.role = "hidden"
    room:broadcastProperty(p, "role")
  end

  room:addSkill(Fk.skills["variationheg_rule"]) --应变规则

  -- for adjustSeats
  room.players[1].role = "lord"
end

function HegLogic:chooseGenerals()
  local room = self.room
  local generalNum = math.max(room:getSettings('generalNum'), 5)
  room:doBroadcastNotify("ShowToast", Fk:translate("#VariationHegInitialNotices"))

  local lord = room:getLord() --[[@as ServerPlayer]]
  room:setCurrent(lord)
  lord.role = "hidden"

  local trskingdoms={
  ["wei"]="<b><font color='blue'>魏</font>",
  ["shu"]="<b><font color='red'>蜀</font>",
  ["wu"]="<b><font color='green'>吴</font>",
  ["qun"]="<b><font color='grey'>群</font>",
  ["jinv"]="<b><font color='pink'>晋</font>",
}

  local allKingdoms = {} ---@type string[]
  table.forEach(room.general_pile, function(name)
    table.insertIfNeed(allKingdoms, Fk.generals[name].kingdom) -- 假设不会有只出现在副势力的势力
  end)
  table.removeOne(allKingdoms, "wild")
  table.removeOne(allKingdoms, "jinv")--为了测试晋
  table.sort(allKingdoms)

  if #allKingdoms >= 4 then --如果势力大于4个，则ban一个
    local kingdoms = table.random(allKingdoms, 3) --为了测试晋
    local unused = table.filter(allKingdoms, function(k)
      return not table.contains(kingdoms, k)
    end)
    local chinese_kingdoms = {}--转换成中文
    for _, kingdom in ipairs(unused) do
      table.insert(chinese_kingdoms, trskingdoms[kingdom])
    end
    room:sendLog{
      type = "#KingdomFiltered",
      arg = table.concat(chinese_kingdoms, " "),
      toast = true,
    }
     for i = #room.general_pile, 1, -1 do
      local g = Fk.generals[room.general_pile[i]]
      if table.contains(unused, g.kingdom) or table.contains(unused, g.subkingdom) then
        table.remove(room.general_pile, i)
      end
    end
  -- 然后把武将牌堆弄好
    table.insertIfNeed(kingdoms, "jinv")--为了测试晋
    allKingdoms = kingdoms
    room:setBanner("@heg_bankingdom", chinese_kingdoms)
  end
  table.sort(allKingdoms)

  local players = room.players
  local generals = room:getNGenerals(#players * generalNum)
  table.shuffle(generals)
  local req = Request:new(players, "AskForGeneral")
  req.timeout = self.room:getSettings('generalTimeout') --选将时间

  for k, p in ipairs(players) do
    -- local arg = { map = table.map }
    local arg = table.slice(generals, (k - 1) * generalNum + 1, k * generalNum + 1)
    table.sort(arg, function(a, b) return Fk.generals[a].kingdom > Fk.generals[b].kingdom end)

    for idx, _ in ipairs(arg) do
      local g = Fk.generals[arg[idx]]
      local g2 = Fk.generals[arg[idx + 1]]
      if (g.kingdom == g2.kingdom and g.kingdom ~= "wild") or (g.kingdom == "wild" and g2.kingdom ~= "wild") or
        (g.subkingdom ~= nil and g.subkingdom == g2.subkingdom) or g.kingdom == g2.subkingdom or g.subkingdom == g2.kingdom then
          req:setDefaultReply(p, {arg[idx], arg[idx + 1]})
          break
      end
    end

    req:setData(p, {arg, 2, false, true})
  end


  local selected = {}
  for _, p in ipairs(players) do
    local general_ret = req:getResult(p)
    local general, deputy = general_ret[1], general_ret[2]
    room:setPlayerGeneral(p, general, true)
    room:setDeputyGeneral(p, deputy)
    table.insertTableIfNeed(selected, {general, deputy})

    room:setPlayerMark(p, "__heg_general", general)
    room:setPlayerMark(p, "__heg_deputy", deputy)

    room:setPlayerGeneral(p, "anjiang", true)
    room:setDeputyGeneral(p, "anjiang")


  end

  generals = table.filter(generals, function(g) return not table.contains(selected, g) end)
  room:returnToGeneralPile(generals)

  req = Request:new(players, "AskForChoice")
  req.focus_text = "AskForKingdom"
  req.receive_decode = false

  for _, p in ipairs(players) do
    local curGeneral = Fk.generals[p:getMark("__heg_general")]
    local kingdoms = {curGeneral.kingdom, curGeneral.subkingdom}
    curGeneral = Fk.generals[p:getMark("__heg_deputy")]
    if kingdoms[1] == "wild" then
      kingdoms = {curGeneral.kingdom, curGeneral.subkingdom}
      room:setPlayerMark(p, "__heg_wild", 1)
    else
      kingdoms = table.filter(kingdoms, function(k) return curGeneral.kingdom == k or curGeneral.subkingdom == k end)
    end

    req:setData(p, {kingdoms, allKingdoms, "AskForKingdom", "#ChooseHegInitialKingdom"})
    req:setDefaultReply(p, kingdoms[1])
  end


  for _, p in ipairs(players) do
     local kingdomChosen = req:getResult(p)
    room:setPlayerMark(p, "__heg_kingdom", kingdomChosen)  -- 变野后变为wild
    room:setPlayerMark(p, "__heg_init_kingdom", kingdomChosen) -- 保存初始势力
    p.default_reply = ""
    -- p.kingdom = kingdomChosen
    --room:notifyProperty(p, p, "kingdom")
  end
end

function HegLogic:broadcastGeneral()
  local room = self.room
  local players = room.players

  for _, p in ipairs(players) do
    assert(p.general ~= "")
    local general = Fk.generals[p:getMark("__heg_general")]
    local deputy = Fk.generals[p:getMark("__heg_deputy")]
    local dmaxHp = deputy.maxHp + deputy.deputyMaxHpAdjustedValue
    local gmaxHp = general.maxHp + general.mainMaxHpAdjustedValue
    p.maxHp = (dmaxHp + gmaxHp) // 2
    -- p.hp = math.floor((deputy.hp + general.hp) / 2)
    p.hp = p.maxHp
    -- p.shield = math.min(general.shield + deputy.shield, 5)
    p.shield = 0
    -- TODO: setup AI here

    room:broadcastProperty(p, "general")
    room:broadcastProperty(p, "deputyGeneral")
    room:broadcastProperty(p, "maxHp")
    room:broadcastProperty(p, "hp")
    room:broadcastProperty(p, "shield")

    p.role = p:getMark("__heg_wild") == 1 and "wild" or p:getMark("__heg_kingdom") -- general.kingdom -- 为了死亡时log有势力提示

    if (dmaxHp + gmaxHp) % 2 == 1 then
      p:setMark("HalfMaxHpLeft", 1)
      p:doNotify("SetPlayerMark", { p.id, "HalfMaxHpLeft", 1})
    end
    if general:isCompanionWith(deputy) then
      p:setMark("CompanionEffect", 1)
      p:doNotify("SetPlayerMark", { p.id, "CompanionEffect", 1})
    end
  end
end

function HegLogic:prepareDrawPile()
  GameLogic.prepareDrawPile(self)

  local room = self.room
  local allianceCards = table.clone(H.allianceCards)
  local addAllianceMark = function(c)
    for i = #allianceCards, 1, -1 do
      local cc = allianceCards[i]
      if c.name == cc[1] and c.suit == cc[2] and c.number == cc[3] then
        room:setCardMark(c, "@@alliance-public", 1)
        table.remove(allianceCards, i)
        break
      end
    end
  end
  for _, cid in ipairs(room.draw_pile) do
    addAllianceMark(Fk:getCardById(cid))
  end
  for _, cid in ipairs(room.void) do
    addAllianceMark(Fk:getCardById(cid))
  end
end

local function addHegSkill(player, skill, room)
  player:addFakeSkill(skill)
  local toget = {table.unpack(skill.related_skills)}
  table.insert(toget, skill)
  for _, s in ipairs(toget) do
    if s:isInstanceOf(TriggerSkill) then
      room.logic:addTriggerSkill(s)
    end
  end
end

function HegLogic:attachSkillToPlayers()
  local room = self.room

  for _, p in ipairs(room.alive_players) do
    -- UI
    p:setMark("@seat", "seat#" .. tostring(p.seat))
    p:doNotify("SetPlayerMark", { p.id, "@seat", "seat#" .. tostring(p.seat)})

    local general = Fk.generals[p:getMark("__heg_general")]
    local skills = general:getSkillNameList(true)
    local hasRevealSkill = false
    for _, sn in ipairs(skills) do
      local s = Fk.skills[sn]
      if not s:hasTag(Skill.DeputyPlace) then
        addHegSkill(p, s, room)
        if not hasRevealSkill and s:hasTag(Skill.Compulsory) then
          hasRevealSkill = true
        end
      end
    end

    local deputy = Fk.generals[p:getMark("__heg_deputy")]
    if deputy then
      skills = deputy:getSkillNameList(true)
      for _, sn in ipairs(skills) do
        local s = Fk.skills[sn]
        if not s:hasTag(Skill.MainPlace) then
          addHegSkill(p, s, room)
          if not hasRevealSkill and s:hasTag(Skill.Compulsory) then
            hasRevealSkill = true
          end
        end
      end
    end

    if hasRevealSkill then
      p:addFakeSkill("reveal_skill&")
    end
  end

  room:doBroadcastNotify("ShowToast", Fk:translate("#VariationHegInitialNotices"))
end

local heg_getlogic = function()
  local h = GameLogic:subclass("HegLogic")
  for k, v in pairs(HegLogic) do
    h[k] = v
  end
  return h
end

heg = fk.CreateGameMode{
  name = "variation_heg_mode",
  minPlayer = 2,
  maxPlayer = 10,
  rule = "zeheg_rule",
  logic = heg_getlogic,
  is_counted = function(self, room)
    return #room.players >= 6
  end,
  whitelist = {
    "sifu_heg_generals",
    "variation_jinstandard",
    "variation_jinld",
    "sifu_heg_ld",
    "jinzhbh",
    "sifu_heg_zhbh",

    "variation_hegcards",
    "variation_excards",
    "variation_strategic_advantage",
  },
  winner_getter = function(self, victim)
    local room = victim.room
    local alive = table.filter(room.alive_players, function(p)
      return not p.surrendered
    end)
    if #alive == 1 then
      local p = alive[1] ---@type ServerPlayer
      p:revealGeneral(false)
      p:revealGeneral(true)
      return p.role
    end

    local winner -- = alive[1]
    for _, p in ipairs(alive) do
      if p.kingdom ~= "unknown" then
        winner = p
        break
      end
    end
    if not winner then return "" end
    local kingdom = H.getKingdom(winner)
    local i = H.getKingdomPlayersNum(room, true)[kingdom]
    for _, p in ipairs(alive) do
      if not H.compareExpectedKingdomWith(p, winner) then
        return ""
      end
      if p.kingdom == "unknown" then
        i = i + 1
      end
    end
    if i > #room.players // 2 and not H.getHegLord(room, winner) then return "" end
    return kingdom
  end,
  surrender_func = function(self, playedTime)
    local winner
    local kingdomCheck = true
    for _, p in ipairs(Fk:currentRoom().alive_players) do
      -- 场上有未明置的主将时不能投降
      if p.general == "anjiang" then
        kingdomCheck = false
        break
      end
      if p ~= Self then
        if not winner then
          winner = p
        elseif not H.compareKingdomWith(winner, p) then
          kingdomCheck = false
          break
        end
      end
    end
    return { { text = "heg: besieged on all sides", passed = kingdomCheck } }
  end,
   reward_punish = function (self, victim, killer)
    local room = victim.room
    if killer then
      if killer.kingdom ~= "unknown" and not killer.dead then
        local times = 1
        if room:getBanner("additional_reward") then --贾充
          times = 1 + room:getBanner("additional_reward")
        end
        -- 因为建国，修改奖惩；如果还没建国
        if killer.kingdom == "wild" and killer:getMark("__heg_construct_wild") == 0 and killer:getMark("__heg_join_wild") == 0 then
          killer:drawCards(times * 3, "kill")
        elseif H.compareKingdomWith(killer, victim) then
          if not (room.logic:getCurrentEvent():findParent(GameEvent.Death, true).data.extra_data or {}).ignorePunishment then --朱灵
          if not (room.logic:getCurrentEvent():findParent(GameEvent.Death, true).data.extra_data or {}).jinld__tousui then --二成
          killer:throwAllCards("he")
          else
          local targets = table.filter(room.alive_players, function(p) return H.compareKingdomWith(killer, p) end)
          room:sortByAction(targets)
            for _, p in ipairs(targets) do
              p:throwAllCards("he")
            end
          end
        end
        else
          if not (room.logic:getCurrentEvent():findParent(GameEvent.Death, true).data.extra_data or {}).jinld__tousui then --二成
          killer:drawCards(times * (H.getSameKingdomPlayersNum(room, victim) + 1), "kill")
          else
          local targets = table.filter(room.alive_players, function(p) return H.compareKingdomWith(killer, p) end)
          room:sortByAction(targets)
             for _, p in ipairs(targets) do
              p:drawCards(times * (H.getSameKingdomPlayersNum(room, victim) + 1), "kill")
           end
         end
       end
      end
    end
    if string.find(victim.general, "lord") then
      local players = (table.filter(room.players, function(p) return
        (p:getMark("__heg_kingdom") == victim.kingdom or (p.dead and p.kingdom == victim.kingdom)) and p ~= victim and p.kingdom ~= "wild"
      end))
      room:sortByAction(players)
      local function wildChooseKingdom(player, generalName)
        local allKingdoms ={"wei", "shu", "wu", "qun", "jinv", "unknown", "hidden"}

        local choice
        local all_choices = table.clone(H.wildKingdoms)
        local choices = table.clone(all_choices)
        for _, p in ipairs(room.players) do
          table.removeOne(choices, p.role)
        end
        if player.general == generalName and H.kingdomMapper[generalName] and H.kingdomMapper[generalName] ~= player.role then -- 野心家钦定
          if table.contains(choices, H.kingdomMapper[generalName]) then
            choice = H.kingdomMapper[generalName]
          else
            choice = room:askToChoice(player, {
              choices = choices,
              skill_name = "variationheg_rule",
              prompt = "#wild-choose",
              cancelable = false,
              all_choices = all_choices,
            })
          end
        elseif table.contains(allKingdoms, player.role) then
          choice = room:askToChoice(player, {
            choices = choices,
            skill_name = "variationheg_rule",
            prompt = "#wild-choose",
            cancelable = false,
            all_choices = all_choices,
          })
        end
        if choice then
          player.role = choice
          room:setPlayerProperty(player, "role_shown", true)
          room:broadcastProperty(player, "role")
          room:sendLog{
            type = "#WildChooseKingdom",
            from = player.id,
            arg = choice,
            arg2 = "wild",
          }
        end
      end
      for _, p in ipairs(players) do
        local oldKingdom = p.kingdom
        room:setPlayerMark(p, "__heg_kingdom", "wild")
        if oldKingdom ~= "unknown" then
          room:setPlayerProperty(p, "kingdom", "wild")
          if not p.dead then
            wildChooseKingdom(p, p.general)
          end
        end
      end
    end
  end,
  build_draw_pile = function(self)
    local draw, void = GameMode.buildDrawPile(self)

    for i = #draw, 1, -1 do
      local card = Fk:getCardById(draw[i])
      if H.convertCards[card.name] then
        local name = H.convertCards[card.name]
        if table.find(draw, function(c)
          return Fk:getCardById(c).name == name
        end) then
          local id = table.remove(draw, i)
          table.insert(void, id)
        end
      end
    end

    return draw, void
  end,
}

local notice = "此模式为<b><font color='purple'>应变国战模式<br><b><font color='red'>开局随机ban一个势力<br><font color='black'>牌堆为<font color='green'>国战应变篇</font></b>"

Fk:loadTranslationTable{
  ["variation_heg_mode"] = "应变国战",
  [":variation_heg_mode"] = heg_description,
  ["variationheg_rule"] = "国战规则",
  ["#VariationHegInitialNotices"] = notice,
  ["jinv"] = "晋",
}

return heg